/*
    Project:        Home Power Control
    File:           HPCLogger.cpp
    Author:         christian@karunamusic.at
    Date:           01.2015
    Description:    Basic implementation of a logger-class to send logmessages with
                    various loglevels via signals to all connected subscribers.
 */

#include <QDate>
#include <QTime>
#include <QMap>
#include "HPCLogger.h"

#include <iostream>

// Definition (and initialization) of static attributes
HPCLogger* HPCLogger::m_Log = 0;
QMutex HPCLogger::m_Mutex;
QMap<QString,TLogLevel> HPCLogger::m_LogLevels =
{
    {"disabled", disabled},
    {"fatal",    fatal   },
    {"error",    error   },
    {"warning",  warning },
    {"info",     info    },
    {"debug",    debug   },
    {"trace",    trace   }
};
HPCLogMessage::HPCLogMessage(  const TLogLevel     logLevel,
                               const QString&      sourceFile,
                               const unsigned int  codeLine,
                               const QString&      message )
    : QObject(), m_LogLevel(logLevel), m_SourceFile(sourceFile), m_CodeLine(codeLine), m_Message(message)
{
    m_TimeStamp  = QDate::currentDate().toString("dd.MM.yyyy") + " " + QTime::currentTime().toString("hh:mm:ss.zzz");
}

std::ostream& operator << ( std::ostream& dest, const HPCLogMessage& msg )
{
    dest << "[" << msg.TimeStamp().toStdString() << "]";
    if ( msg.LogLevel() == trace )
    {
        dest << "(" << msg.SourceFile().toStdString() << "|" << msg.CodeLine() << ")";
    }
    dest << ": " << msg.Message().toStdString();
    return dest;
}

std::ostream& operator << ( std::ostream& dest, const TLogLevel lv )
{
    dest << HPCLogger::LogLevelToString(lv).toStdString();
    return dest;
}

HPCLogger::HPCLogger()
    : QObject()
{
}

HPCLogger::~HPCLogger()
{
    if (m_Log != 0)
    {
        m_Mutex.lock();
        delete m_Log;
        m_Mutex.unlock();
    }
}

HPCLogger* HPCLogger::getInstance()
{
    if (m_Log == 0)
    {
        m_Mutex.lock();
        m_Log = new HPCLogger;
        m_Mutex.unlock();
    }
    return m_Log;
}

void HPCLogger::print(const TLogLevel    logLevel,
                      const QString&     sourceFile,
                      const unsigned int codeLine,
                      const QString&     message)
{
    if ( !message.length() )
        return;

    m_Mutex.lock();
    HPCLogMessage *lm = new HPCLogMessage(logLevel,sourceFile,codeLine,message);
    emit LogEvent(*lm);
    delete lm;
    m_Mutex.unlock();
}

QString HPCLogger::LogLevelToString( TLogLevel logLevel )
{
    return m_LogLevels.key( logLevel,QString("disabled") );
}

TLogLevel HPCLogger::StringToLogLevel( const QString& logLevel )
{
    if ( m_LogLevels.contains(logLevel) )
        return m_LogLevels.value(logLevel);

    return disabled;
}
